package handler

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"github.com/yejingxuan/accumulate/application"
	"github.com/yejingxuan/accumulate/infrastructure/analyse"
	"github.com/yejingxuan/accumulate/infrastructure/config"
	"github.com/yejingxuan/accumulate/infrastructure/logger"
	"github.com/yejingxuan/accumulate/infrastructure/utils"
	"github.com/yejingxuan/accumulate/interface/dto"
	"go.uber.org/zap"
	"strconv"
	"strings"
)

type stockHandler struct {
	stockApp application.StockAppInterface
}

//stockHandler 构造函数
func NewStockHandler(stockApp application.StockAppInterface) *stockHandler {
	return &stockHandler{stockApp}
}

// @Summary 查询stock数据
// @Tags 信息获取
// @Router /accumulate/v1/info/stock/query [post]
// @Param object body dto.QueryStockReq true "输入参数"
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) QueryStockPage(c *gin.Context) {
	req := &dto.QueryStockReq{}
	if err := c.ShouldBindJSON(req); err != nil {
		dto.JSON(c, dto.ErrBadRequest, err)
		return
	}
	logger.Info("查询stock数据", zap.Any("req", req))
	data, total, err := h.stockApp.QueryStockPage(req)
	if err != nil {
		dto.JSON(c, dto.Error, err)
		return
	}

	handleData := make([]dto.StockResp, 0)
	for _, item := range data {
		info := dto.StockResp{}
		utils.StructAssign(&info, &item)
		//标签转换
		for tagInfo := range analyse.CalculateTags {
			item.Tags = strings.ReplaceAll(item.Tags, tagInfo.Value, tagInfo.Desc)
		}
		if len(item.Tags) > 0 {
			info.TagArray = strings.Split(item.Tags, ",")
		}
		//状态转换
		info.ReadStatus = config.ReadStatusMap[item.ReadStatus]
		//日期转换
		info.ReadTimeStr = utils.TransformTimeToStr(item.ReadTime)
		if info.ReadTimeStr == "0001-01-01" {
			info.ReadTimeStr = ""
		}
		//市值转换
		i, _ := decimal.NewFromInt(item.MarketCapital).
			Div(decimal.NewFromInt(100000000)).Float64()
		value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", i), 64)
		info.MarketCapitalFloat = value
		//关注价格转换
		info.ReadPrice = item.ReadPrice
		if item.Service.ReadPrice == 0 {
			info.ReadPrice = nil
		}
		//评论转换
		info.Comment = item.Comment
		//关注至今
		if item.ReadPrice != 0 {
			f1, _ := decimal.NewFromFloat(item.Current - item.ReadPrice).
				Div(decimal.NewFromFloat(item.ReadPrice)).Float64()
			f2, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", f1*100), 64)
			info.ReadPercent = f2
		}

		handleData = append(handleData, info)
	}

	res := &dto.QueryStockResp{Records: handleData, Total: total}
	dto.JSON(c, dto.Success, res)
}

// @Summary 关注stock
// @Tags 信息获取
// @Router /accumulate/v1/info/stock/follow [post]
// @Param object body dto.FollowStockReq true "输入参数"
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) Follow(c *gin.Context) {
	req := &dto.FollowStockReq{}
	if err := c.ShouldBindJSON(req); err != nil {
		dto.JSON(c, dto.ErrBadRequest, err)
		return
	}
	logger.Info("关注stock", zap.Any("req", req))
	err := h.stockApp.Follow(req)
	if err != nil {
		dto.JSON(c, dto.Error, err)
		return
	}
	dto.JSON(c, dto.Success, nil)
}

// @Summary 获取stock详细信息
// @Tags 信息获取
// @Router /accumulate/v1/info/stock/{code} [get]
// @Param code path string true "stock-code"
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) GetStockInfo(c *gin.Context) {
	code := c.Param("code")
	res, err := h.stockApp.GetStockInfoByCode(code)
	if err != nil {
		logger.Error("GetStockInfoById err", zap.Any("err", err))
		dto.JSON(c, dto.ErrBadRequest, err)
		return
	}
	dto.JSON(c, dto.Success, res)
}

// @Summary 查询tag数据
// @Tags 信息获取
// @Router /accumulate/v1/info/tags [get]
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) GetStockTags(c *gin.Context) {
	res := make([]dto.TagResp, 0)
	for key := range analyse.CalculateTags {
		res = append(res, dto.TagResp{
			Name:  key.Desc,
			Value: key.Value,
		})
	}
	dto.JSON(c, dto.Success, res)
}

// @Summary 评论stock
// @Tags 信息获取
// @Router /accumulate/v1/info/stock/comment [post]
// @Param object body dto.CommentStockReq true "输入参数"
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) Comment(c *gin.Context) {
	req := &dto.CommentStockReq{}
	if err := c.ShouldBindJSON(req); err != nil {
		dto.JSON(c, dto.ErrBadRequest, err)
		return
	}
	logger.Info("评论stock", zap.Any("req", req))
	err := h.stockApp.Comment(req)
	if err != nil {
		dto.JSON(c, dto.Error, err)
		return
	}
	dto.JSON(c, dto.Success, nil)

}

// @Summary 更新stock基本数据
// @Tags 任务执行
// @Router /accumulate/v1/exec/update/stock [post]
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) UpdateStock(c *gin.Context) {
	err := h.stockApp.UpdateStock()
	if err != nil {
		logger.Error("UpdateAll err", zap.Any("err", err))
		dto.JSON(c, dto.Error, err)
		return
	}
	dto.JSON(c, dto.Success, nil)
}

// @Summary 更新kline数据
// @Tags 任务执行
// @Router /accumulate/v1/exec/update/kline [post]
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) UpdateKline(c *gin.Context) {
	go h.stockApp.UpdateKline()
	dto.JSON(c, dto.Success, nil)
}

// @Summary 更新kline数据的进度
// @Tags 任务执行
// @Router /accumulate/v1/exec/update/kline/process [get]
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) KlineProcess(c *gin.Context) {
	res := h.stockApp.KlineProcess()
	dto.JSON(c, dto.Success, res)
}

// @Summary 数据分析计算
// @Tags 任务执行
// @Router /accumulate/v1/exec/analyse [post]
// @Success 200 {string} json "{"code":0,"data":{},"msg":"ok"}"
func (h stockHandler) AnalyseInfo(c *gin.Context) {
	err := h.stockApp.AnalyseInfo()
	if err != nil {
		logger.Error("AnalyseInfo err", zap.Any("err", err))
		dto.JSON(c, dto.Error, err)
		return
	}
	dto.JSON(c, dto.Success, nil)
}
